home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-21 | 19.3 KB | 587 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWBestFH.h
- // Release Version: $ 1.0d1 $
- //
- // Creation Date: 3/28/94
- //
- // Copyright: © 1993, 1994 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef FWBESTFH_H
- #define FWBESTFH_H
-
- #ifndef FWMEMORH_H
- #include <FWMemorH.h>
- #endif
-
-
- //========================================================================================
- // Forward class declarations
- //========================================================================================
-
- class FW_CPrivBestFitBlock;
- class FW_CBestFitHeap;
-
-
- //========================================================================================
- // STRUCT FW_SPrivBestFitBlockFreeListLinks
- //
- // The following fields are only present in free blocks. They are used to link the free
- // block into the free block tree. The address of a free block is also stored at the end
- // of the block and must be accounted for in the minimum block size.
- //========================================================================================
-
- struct FW_SPrivBestFitBlockFreeListLinks
- {
- FW_CPrivBestFitBlock* fParent;
- FW_CPrivBestFitBlock* fLeft;
- FW_CPrivBestFitBlock* fRight;
- };
-
-
- //========================================================================================
- // STRUCT FW_SPrivBestFitBlockHeader
- //========================================================================================
-
- // The fBits field of FW_SPrivBestFitBlockHeader contains five fields. The following masks are
- // used to get and set the fields. The block type field is used to distinguish best fit
- // blocks from chunky blocks and must be the first four bits of the last byte in fBits.
-
- #ifdef BUILD_WIN
- // Bytes are in reverse order in a long.
-
- const unsigned long BestFitBlockHeader_kSizeMask = 0x00FFFFFF;
- const unsigned long BestFitBlockHeader_kSizeShift = 0;
-
- const unsigned long BestFitBlockHeader_kBlockTypeMask = 0xF0000000;
- const unsigned long BestFitBlockHeader_kBlockTypeShift = 28;
-
- const unsigned long BestFitBlockHeader_kBusyMask = 0x08000000;
- const unsigned long BestFitBlockHeader_kBusyShift = 27;
-
- const unsigned long BestFitBlockHeader_kPreviousBusyMask = 0x04000000;
- const unsigned long BestFitBlockHeader_kPreviousBusyShift = 26;
-
- const unsigned long BestFitBlockHeader_kMagicNumberMask = 0x03000000;
- const unsigned long BestFitBlockHeader_kMagicNumberShift = 24;
- #else
- const unsigned long BestFitBlockHeader_kSizeMask = 0xFFFFFF00;
- const unsigned long BestFitBlockHeader_kSizeShift = 8;
-
- const unsigned long BestFitBlockHeader_kBlockTypeMask = 0x000000F0;
- const unsigned long BestFitBlockHeader_kBlockTypeShift = 4;
-
- const unsigned long BestFitBlockHeader_kBusyMask = 0x00000008;
- const unsigned long BestFitBlockHeader_kBusyShift = 3;
-
- const unsigned long BestFitBlockHeader_kPreviousBusyMask = 0x00000004;
- const unsigned long BestFitBlockHeader_kPreviousBusyShift = 2;
-
- const unsigned long BestFitBlockHeader_kMagicNumberMask = 0x00000003;
- const unsigned long BestFitBlockHeader_kMagicNumberShift = 0;
- #endif
-
- struct FW_SPrivBestFitBlockHeader
- {
- unsigned long fBits;
- FW_SPrivBestFitBlockFreeListLinks fFreeLinks;
- };
-
-
- //========================================================================================
- // CLASS FW_CPrivBestFitBlock
- //========================================================================================
-
- #ifdef BUILD_WIN16
- const FW_BlockSize BestFitBlock_kMaxBlockSize = 60L * 1024L;
- // Block size limited by 64K limit of far pointers. Allow 4K for overhead in the
- // various layers.
- #else
- const FW_BlockSize BestFitBlock_kMaxBlockSize = 0x00FFFFFF;
- #endif
-
- class FW_CPrivBestFitBlock
- {
- public:
-
- enum
- {
- kBusyOverhead = sizeof(unsigned long),
- kMinBlockSize = sizeof(FW_SPrivBestFitBlockHeader) + sizeof(void *),
- kBlockTypeId = FW_CMemoryHeap::kBlockTypeId + 1,
- kMagicNumber = 0x3
- };
-
-
- Boolean operator>(const FW_CPrivBestFitBlock& blk) const;
- Boolean operator<(const FW_CPrivBestFitBlock& blk) const;
- Boolean operator>=(const FW_CPrivBestFitBlock& blk) const;
- Boolean operator<=(const FW_CPrivBestFitBlock& blk) const;
- Boolean operator==(const FW_CPrivBestFitBlock& blk) const;
- Boolean operator!=(const FW_CPrivBestFitBlock& blk) const;
- FW_CPrivBestFitBlock& operator=(const FW_CPrivBestFitBlock& blk);
-
- inline void operator delete(void *) { };
- void* operator new(SIZE_T, void* ptr);
- void* operator new(SIZE_T);
-
- FW_CPrivBestFitBlock(int busy,
- int prevBusy,
- long size);
- FW_CPrivBestFitBlock(const FW_CPrivBestFitBlock& otherBlock);
-
- Boolean GetBusy() const;
- FW_CPrivBestFitBlock* GetLeft() const;
- unsigned int GetMagicNumber() const;
- FW_CPrivBestFitBlock* GetNext() const;
- FW_CPrivBestFitBlock* GetParent() const;
- Boolean GetPreviousBusy() const;
- FW_CPrivBestFitBlock* GetRight() const;
- FW_BlockSize GetSize() const;
- unsigned short GetBlockType() const;
-
- void SetBusy(Boolean busy);
- void SetLeft(FW_CPrivBestFitBlock* left);
- void SetNext(FW_CPrivBestFitBlock* fNext);
- void SetParent(FW_CPrivBestFitBlock* parent);
- void SetPrevBusy(Boolean busy);
- void SetRight(FW_CPrivBestFitBlock* right);
- void SetSize(FW_BlockSize size);
- void SetBlockType(unsigned long blockType);
- void SetMagicNumber(unsigned long magicNumber);
-
- void StuffAddressAtEnd();
-
- protected:
-
- private:
- FW_SPrivBestFitBlockHeader fHeader;
- };
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator delete
- //----------------------------------------------------------------------------------------
- /*
- inline void FW_CPrivBestFitBlock::operator delete(void*)
- {
- }
- */
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator new
- //----------------------------------------------------------------------------------------
-
- inline void* FW_CPrivBestFitBlock::operator new(SIZE_T, void* ptr)
- {
- return ptr;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator new
- //----------------------------------------------------------------------------------------
-
- inline void* FW_CPrivBestFitBlock::operator new(SIZE_T)
- {
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator>=
- //----------------------------------------------------------------------------------------
-
- inline Boolean FW_CPrivBestFitBlock::operator>=(const FW_CPrivBestFitBlock& blk) const
- {
- return *this > blk || *this == blk;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator<=
- //----------------------------------------------------------------------------------------
-
- inline Boolean FW_CPrivBestFitBlock::operator<=(const FW_CPrivBestFitBlock& blk) const
- {
- return *this < blk || *this == blk;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator!=
- //----------------------------------------------------------------------------------------
-
- inline Boolean FW_CPrivBestFitBlock::operator!=(const FW_CPrivBestFitBlock& blk) const
- {
- return !(*this == blk);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator=
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock& FW_CPrivBestFitBlock::operator=(const FW_CPrivBestFitBlock& blk)
- {
- fHeader = blk.fHeader;
- return (*this);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::FW_CPrivBestFitBlock
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock::FW_CPrivBestFitBlock(const FW_CPrivBestFitBlock& blk) :
- fHeader(blk.fHeader)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetBusy
- //----------------------------------------------------------------------------------------
-
- inline Boolean FW_CPrivBestFitBlock::GetBusy() const
- {
- return (fHeader.fBits & BestFitBlockHeader_kBusyMask) != 0 ? true : false;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetLeft
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock* FW_CPrivBestFitBlock::GetLeft() const
- {
- return fHeader.fFreeLinks.fLeft;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetMagicNumber
- //----------------------------------------------------------------------------------------
-
- inline unsigned int FW_CPrivBestFitBlock::GetMagicNumber() const
- {
- return (fHeader.fBits & BestFitBlockHeader_kMagicNumberMask)
- >> BestFitBlockHeader_kMagicNumberShift;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetNext
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock* FW_CPrivBestFitBlock::GetNext() const
- {
- return fHeader.fFreeLinks.fParent;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetParent
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock* FW_CPrivBestFitBlock::GetParent() const
- {
- return fHeader.fFreeLinks.fParent;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetPreviousBusy
- //----------------------------------------------------------------------------------------
-
- inline Boolean FW_CPrivBestFitBlock::GetPreviousBusy() const
- {
- return (fHeader.fBits & BestFitBlockHeader_kPreviousBusyMask) != 0 ? true : false;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetRight
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock* FW_CPrivBestFitBlock::GetRight() const
- {
- return fHeader.fFreeLinks.fRight;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetSize
- //----------------------------------------------------------------------------------------
-
- inline FW_BlockSize FW_CPrivBestFitBlock::GetSize() const
- {
- return (fHeader.fBits & BestFitBlockHeader_kSizeMask)
- >> BestFitBlockHeader_kSizeShift;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::GetBlockType
- //----------------------------------------------------------------------------------------
-
- inline unsigned short FW_CPrivBestFitBlock::GetBlockType() const
- {
- return (fHeader.fBits & BestFitBlockHeader_kBlockTypeMask)
- >> BestFitBlockHeader_kBlockTypeShift;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetBusy
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetBusy(Boolean busy)
- {
- if (busy)
- fHeader.fBits |= BestFitBlockHeader_kBusyMask;
- else
- fHeader.fBits &= ~BestFitBlockHeader_kBusyMask;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetLeft
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetLeft(FW_CPrivBestFitBlock* left)
- {
- fHeader.fFreeLinks.fLeft = left;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetNext
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetNext(FW_CPrivBestFitBlock* fNext)
- {
- // The fParent field is used both for a parent and a next pointer on different
- // occasions.
-
- fHeader.fFreeLinks.fParent = fNext;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetParent
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetParent(FW_CPrivBestFitBlock* parent)
- {
- fHeader.fFreeLinks.fParent = parent;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetPrevBusy
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetPrevBusy(Boolean busy)
- {
- if (busy)
- fHeader.fBits |= BestFitBlockHeader_kPreviousBusyMask;
- else
- fHeader.fBits &= ~BestFitBlockHeader_kPreviousBusyMask;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetRight
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetRight(FW_CPrivBestFitBlock* right)
- {
- fHeader.fFreeLinks.fRight = right;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetSize
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetSize(FW_BlockSize size)
- {
- fHeader.fBits &= ~BestFitBlockHeader_kSizeMask;
- fHeader.fBits |= (size << BestFitBlockHeader_kSizeShift)
- & BestFitBlockHeader_kSizeMask;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetBlockType
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetBlockType(unsigned long blockType)
- {
- fHeader.fBits &= ~BestFitBlockHeader_kBlockTypeMask;
- fHeader.fBits |= (blockType << BestFitBlockHeader_kBlockTypeShift)
- & BestFitBlockHeader_kBlockTypeMask;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::SetMagicNumber
- //----------------------------------------------------------------------------------------
-
- inline void FW_CPrivBestFitBlock::SetMagicNumber(unsigned long magicNumber)
- {
- fHeader.fBits &= ~BestFitBlockHeader_kMagicNumberMask;
- fHeader.fBits |= (magicNumber << BestFitBlockHeader_kMagicNumberShift)
- & BestFitBlockHeader_kMagicNumberMask;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::FW_CPrivBestFitBlock
- //----------------------------------------------------------------------------------------
-
- inline FW_CPrivBestFitBlock::FW_CPrivBestFitBlock(int busy,
- int previousBusy,
- long size)
- {
- SetParent(NULL);
- SetRight(NULL);
- SetLeft(NULL);
- SetBlockType(kBlockTypeId);
- SetBusy(busy);
- SetPrevBusy(previousBusy);
- SetSize(size);
- SetMagicNumber(kMagicNumber);
-
- if (!busy)
- this->StuffAddressAtEnd();
- }
-
-
- //========================================================================================
- // CLASS FW_CPrivBestFitSegment
- //
- // The FW_CBestFitHeap allocates memory from the system in segments. The segments are
- // linked together in a list so that When the heap is destroyed all segments can be
- // freed.
- //
- //========================================================================================
-
- class FW_CPrivBestFitSegment
- {
- public:
-
- friend FW_CBestFitHeap;
-
- enum
- {
- kSegmentPrefixSize = 12,
- kSegmentSuffixSize = 4,
- kSegmentOverhead = kSegmentPrefixSize + kSegmentSuffixSize
- };
-
- Boolean AddressInSegment(void* ptr);
-
- private:
- void *fSegmentSpace;
- unsigned long fSegmentSize;
- FW_CPrivBestFitSegment *fNextSegment;
-
- FW_CPrivBestFitSegment(const FW_CPrivBestFitSegment& blk);
- FW_CPrivBestFitSegment& operator=(const FW_CPrivBestFitSegment& blk);
- // This class shouldn't be copied.
- };
-
- //----------------------------------------------------------------------------------------
- // INLINES FW_CPrivBestFitSegment
- //----------------------------------------------------------------------------------------
-
- inline Boolean FW_CPrivBestFitSegment::AddressInSegment(void* ptr)
- {
- return ptr >= fSegmentSpace &&
- ptr <= (void*) ((FW_BytePtr) fSegmentSpace + fSegmentSize);
- }
-
-
- //========================================================================================
- // CLASS FW_CPrivFreeBlockTree
- //
- // Binary tree for storing free blocks. Dependent on the structure and
- // implementation of FW_CPrivBestFitBlock.
- //
- //========================================================================================
-
- class FW_CPrivFreeBlockTree
- {
- public:
- FW_CPrivFreeBlockTree();
- FW_CPrivFreeBlockTree(const FW_CPrivFreeBlockTree& blk);
-
- FW_CPrivFreeBlockTree& operator=(const FW_CPrivFreeBlockTree& blk);
-
- void AddBlock(FW_CPrivBestFitBlock* blk);
- void TreeInfo(unsigned long& bytesFree,
- unsigned long& numberOfNodes) const;
- void RemoveBlock(FW_CPrivBestFitBlock* blk);
- FW_CPrivBestFitBlock* SearchForBlock(FW_BlockSize size,
- void* blk,
- FW_CPrivBestFitBlock** insertLeaf = NULL);
-
- #ifdef FW_DEBUG
- void CheckTree() const;
- void PrintTree() const;
- #endif
-
- protected:
- FW_CPrivBestFitBlock* GetSuccessorBlk(FW_CPrivBestFitBlock* blk);
- void TreeInfoHelper(FW_CPrivBestFitBlock* blk,
- unsigned long& bytesFree,
- unsigned long& numberOfNodes) const;
-
- #ifdef FW_DEBUG
- void CheckTreeHelper(FW_CPrivBestFitBlock* blk) const;
- void PrintTreeHelper(FW_CPrivBestFitBlock* blk,
- int level = 0) const;
- #endif
-
- private:
- FW_CPrivBestFitBlock fRoot;
-
- };
-
-
- //========================================================================================
- // CLASS FW_CBestFitHeap
- //
- // Memory allocation heap using the best fit allocation strategy.
- //
- //========================================================================================
-
- class FW_CBestFitHeap : public FW_CMemoryHeap
- {
- public:
-
- virtual unsigned long BytesFree() const;
- virtual unsigned long HeapSize() const;
-
- FW_CBestFitHeap(unsigned long sizeInitial, unsigned long sizeIncrement = 0);
- virtual~ FW_CBestFitHeap();
-
- void IBestFitHeap(); // MEB
- void ExpandHeap(unsigned long sizeInitial, unsigned long sizeIncrement); // MEB
-
- #ifdef FW_DEBUG
- virtual void Check() const;
- virtual Boolean IsMyBlock(void* blk) const;
- virtual void Print(char* msg = "") const;
- #endif
-
- protected:
-
- void AddToFreeBlocks(FW_CPrivBestFitBlock* blk);
- FW_CPrivBestFitBlock* Coalesce(FW_CPrivBestFitBlock* blk);
- void CreateNewSegment(unsigned long size);
- void DeleteSegments();
- void GrowHeap(unsigned long sizeIncrement);
- void RemoveFromFreeBlocks(FW_CPrivBestFitBlock* blk);
- FW_CPrivBestFitBlock* SearchFreeBlocks(FW_BlockSize size);
-
- virtual void* DoAllocate(FW_BlockSize size, FW_BlockSize& allocatedSize);
- virtual FW_BlockSize DoBlockSize(const void* block) const;
- virtual void DoFree(void*);
- virtual void DoReset();
-
- #ifdef FW_DEBUG
- virtual void CompilerCheck();
- virtual Boolean DoIsValidBlock(void* blk) const;
- #endif
-
- private:
- FW_CPrivBestFitSegment* fSegments;
- unsigned long fSizeIncrement;
- unsigned long fSizeInitial;
- FW_CPrivFreeBlockTree fFreeTree;
-
- FW_CBestFitHeap(const FW_CBestFitHeap& blk);
- FW_CBestFitHeap& operator=(const FW_CBestFitHeap& blk);
- // This class shouldn't be copied.
- };
-
- #endif
-